package com.sunlands.deskmate.exception;

import com.sunlands.deskmate.common.intercept.AutoLogAspect;
import com.sunlands.deskmate.constant.dic.SYS_EMAIL;
import com.sunlands.deskmate.service.DicServiceImpl;
import com.sunlands.deskmate.util.HttpUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.Asserts;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static com.sunlands.deskmate.constant.dic.SYS_EMAIL.errormailgroup;
import static com.sunlands.deskmate.constant.dic.SYS_EMAIL.sendurl;

/**
 * Created with IntelliJ IDEA.
 * User: xiyuefei
 * Date: 2018/4/8
 * Time: 下午3:35
 */
@Data
@Component
@Slf4j
public class SendExceptionUtil {
    @Value("${spring.application.name}")
    private String sysinfo;
    @Value("${spring.profiles.active}")
    private String sysdev;

    @Resource(name = "sendError")
    private AsyncTaskExecutor sendError;

    @Autowired
    private DicServiceImpl dicService;
    Timer timer = new Timer();
    private static ConcurrentHashMap<String, Integer> limiterMap = new ConcurrentHashMap();

    /**
     * 平台邮件报警限流方法，根据异常类型分类一分钟只发送用同一种异常一封邮件
     *
     * @param emailTitle
     * @param emails
     * @param msg
     * @param ex
     */
    public synchronized void sendEmail(String emailTitle, String emails, String msg, Exception ex) {
        Asserts.notBlank(emailTitle, "邮件标题不能为空");
        Asserts.notBlank(emails, "Email不能为空");
        Asserts.notBlank(msg, "邮件内容不能为空");

        sendError.execute(() -> {
            try {
                delaySend(emailTitle, emails, msg, ex);
            } catch (Exception e) {
                log.error("发送邮件异常，e={}", e);
            }
        });
    }

    private synchronized void delaySend(String emailTitle, String emails, String msg, Exception ex) {
        SimpleDateFormat sdfAll = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String key = ex.getClass().getName() + "_" + sdfAll.format(new Date());
        if (limiterMap.get(key) != null) {
            limiterMap.put(key, limiterMap.get(key) + 1);
            return;
        }
        limiterMap.put(key, 1);
        // 一分钟后发送邮件

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    log.info("sendEmail emails = {},emailTitle = {},msg = {} 一分钟发生次数 = {}", emails, emailTitle, msg, limiterMap.get(key));
                    InetAddress address = InetAddress.getLocalHost();
                    String hostAddress = address.getHostAddress();
                    Map<String, Object> requestEntity = new HashMap<String, Object>();
                    requestEntity.put("env", sysdev);
                    requestEntity.put("sys", sysinfo);
                    requestEntity.put("title", emailTitle + "(一分钟发生次数" + limiterMap.get(key) + "次)");
                    requestEntity.put("emailAddr", emails);
                    requestEntity.put("ip", hostAddress);
                    requestEntity.put("msg", ex.getClass().getName() + "\n" + msg + "\n" + ex.fillInStackTrace());
                    requestEntity.put("异常一分钟出现次数", limiterMap.get(key));
                    String str = HttpUtil.doPost(getSendUrl(), requestEntity);
                    //发送邮件后清除记录
                    limiterMap.remove(key);
                    log.info("发送邮件结果：{}", str);
                } catch (Exception e) {
                    log.error("发送邮件异常，e={}", e);
                }

            }
        }, 1000 * 60);
    }

    private String getSendUrl() {
        return dicService.findByCode(SYS_EMAIL.dicName()).filter(sendurl.name()).getData();
    }

    private String getErrormailgroup() {
        return dicService.findByCode(SYS_EMAIL.dicName()).filter(errormailgroup.name()).getData();
    }

    public void sendEmail(String emailTitle, String emails, String msg) {

        Asserts.notBlank(emailTitle, "邮件标题不能为空");
        Asserts.notBlank(emails, "Email不能为空");
        Asserts.notBlank(msg, "邮件内容不能为空");
        sendError.execute(() -> {
            try {
                log.info("sendEmail emails={},emailTitle={},msg={}", emails, emailTitle, msg);
                InetAddress address = InetAddress.getLocalHost();
                String hostAddress = address.getHostAddress();
                Map<String, Object> requestEntity = new HashMap<String, Object>();
                requestEntity.put("env", sysdev);
                requestEntity.put("sys", sysinfo);
                requestEntity.put("title", emailTitle);
                requestEntity.put("emailAddr", emails);
                requestEntity.put("ip", hostAddress);
                requestEntity.put("msg", msg);

                String str = HttpUtil.doPost(getSendUrl(), requestEntity);
                log.info("发送邮件结果：{}", str);
            } catch (Exception e) {
                log.error("", e);
            }
        });

    }

    public void sendException(String msg) {
        sendEmail("系统异常[" + sysinfo + "]", getErrormailgroup(), msg);
    }

    public void sendException(String msg, Exception e) {
        log.info("exception sendemail msg={}", msg);
        if (sysdev.endsWith("dev") || sysdev.endsWith("local")) {
            log.warn("本地调试不发邮件！");
            return;
        }
        msg = "requestId = " + MDC.get(AutoLogAspect.REQUEST_ID) + "\n" + msg;
        sendEmail("系统异常[" + sysinfo + "]", getErrormailgroup(), msg, e);
    }

}
